home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 October / EnigmA AMIGA RUN 01 (1995)(G.R. Edizioni)(IT)[!][issue 1995-10][Aminet 7].iso / Aminet / comm / net / cslip_sana2.lha / slip / device_funcs.c < prev    next >
C/C++ Source or Header  |  1993-06-29  |  49KB  |  1,959 lines

  1. /*
  2. ** $Source: HOG:Other/networking/sana2/src/slip/RCS/device_funcs.c,v $
  3. ** $State: Exp $
  4. ** $Revision: 37.5 $
  5. ** $Date: 92/12/16 13:45:22 $
  6. ** $Author: bj $
  7. **
  8. ** Amiga SANA-II Example SLIP device driver.
  9. **
  10. ** (C) Copyright 1992 Commodore-Amiga, Inc.
  11. **
  12. */
  13.  
  14. #ifndef EOFMODE
  15. # define EOFMODE    1
  16. #endif
  17. #ifndef DEMANDREAD
  18. # define DEMANDREAD    1
  19. #endif
  20.  
  21. #include "slip_device.h"
  22. #if DEBUG
  23. #include "syslog.h"
  24. #else
  25. #define debug(x)
  26. #endif
  27.  
  28. #include <dos/dostags.h>
  29. #include <dos/rdargs.h>
  30. #include <intuition/intuition.h>
  31.  
  32. #include <clib/exec_protos.h>
  33. #include <clib/dos_protos.h>
  34. #include <clib/utility_protos.h>
  35. #include <clib/timer_protos.h>
  36. #include <clib/alib_stdio_protos.h>
  37. #include <clib/intuition_protos.h>
  38.  
  39. #include <pragmas/exec_pragmas.h>
  40. #include <pragmas/dos_pragmas.h>
  41. #include <pragmas/utility_pragmas.h>
  42. #include <pragmas/timer_pragmas.h>
  43. #include <pragmas/intuition_pragmas.h>
  44.  
  45. #include <string.h>
  46. #include "device_protos.h"
  47.  
  48. /*
  49. ** External variables and functions
  50. **
  51. */
  52.  
  53. extern struct SLIPDevice *ExtDeviceBase;
  54. extern ULONG IPToNum(STRPTR ipstr);
  55. extern VOID kprintf(STRPTR fmt, ...);
  56.  
  57. #if CSLIP
  58. const char SLIPName[] = "cslip.device";
  59. #else
  60. const char SLIPName[] = "slip.device";
  61. #endif
  62.  
  63. /*
  64. ** Device Open vector
  65. **
  66. ** a1 - SANA2 IO Request
  67. ** a6 - Pointer to our device base
  68. ** d0 - Unit number
  69. ** d1 - Flags
  70. **
  71. */
  72.  
  73. ULONG ASM DevOpen(REG(a1) struct IOSana2Req *ios2,
  74.           REG(a6) struct SLIPDevice *SLIPDevice,
  75.           REG(d0) ULONG s2unit,
  76.           REG(d1) ULONG s2flags)
  77. {
  78.     struct SLIPDevUnit *sdu;
  79.     struct TagItem *bufftag;
  80.     struct Library *UtilityBase;
  81.     struct BufferManagement *bm;
  82.     ULONG returncode;
  83.     BOOL status = FALSE;
  84.  
  85.     /* Make sure our open remains single-threaded. */
  86.     ObtainSemaphore(&SLIPDevice->sd_Lock);      /* Enforce single threading since we may need to
  87.                            Wait() when starting up the Unit process */
  88.  
  89. #if DEBUG
  90.     initsyslog();
  91. #endif
  92.     SLIPDevice->sd_Device.lib_OpenCnt++;    /* So we won't expunge ourselves... */
  93.  
  94.     if(s2unit < SD_MAXUNITS)    /* Legal Unit? */
  95.     {
  96.     if(sdu = InitSLIPUnit(s2unit))  /* Initialize the Unit */
  97.     {
  98.         if(UtilityBase = OpenLibrary("utility.library",37L)) /* For Tag functions */
  99.         {
  100.         /* Allocate a structure to store the pointers to the callback routines. */
  101.  
  102.         if(bm = AllocMem(sizeof(struct BufferManagement),MEMF_CLEAR|MEMF_PUBLIC))
  103.         {
  104.             /* Note: I don't complain if I can't find pointers to the callback routines.
  105.                  This is because there are some programs that may need to open me, but
  106.                  will never use any device commands that require the callbacks. */
  107.  
  108.             if(bufftag = FindTagItem(S2_CopyToBuff, (struct TagItem *)ios2->ios2_BufferManagement))
  109.             {
  110.             bm->bm_CopyToBuffer = (SANA2_CTB) bufftag->ti_Data;
  111.             }
  112.  
  113.             if(bufftag = FindTagItem(S2_CopyFromBuff, (struct TagItem *)ios2->ios2_BufferManagement))
  114.             {
  115.             bm->bm_CopyFromBuffer = (SANA2_CFB) bufftag->ti_Data;
  116.             }
  117.  
  118.             AddTail((struct List *)&sdu->sdu_BuffMgmt,(struct Node *)bm);
  119.  
  120.             /* Everything went okay. */
  121.             status = TRUE;
  122.             returncode = 0;
  123.             SLIPDevice->sd_Device.lib_OpenCnt++;
  124.             SLIPDevice->sd_Device.lib_Flags &=~LIBF_DELEXP;
  125.             sdu->sdu_Unit.unit_OpenCnt++;
  126.  
  127.             /* Fix up the initial io request */
  128.             ios2->ios2_BufferManagement = (VOID *)bm;
  129.             ios2->ios2_Req.io_Error = 0;
  130.             ios2->ios2_Req.io_Message.mn_Node.ln_Type = NT_REPLYMSG;
  131.             ios2->ios2_Req.io_Unit = sdu;
  132.             ios2->ios2_Req.io_Device = SLIPDevice;
  133.         }
  134.         CloseLibrary(UtilityBase);
  135.         }
  136.     }
  137.     }
  138.     /* See if something went wrong. */
  139.     if(!status)
  140.     {
  141.     ios2->ios2_Req.io_Error = IOERR_OPENFAIL;
  142.     ios2->ios2_Req.io_Unit = (struct Unit *) -1;
  143.     ios2->ios2_Req.io_Device = (struct Device *) -1;
  144.     returncode = IOERR_OPENFAIL;
  145.     }
  146.     SLIPDevice->sd_Device.lib_OpenCnt--;
  147.     ReleaseSemaphore(&SLIPDevice->sd_Lock);
  148.  
  149.     return(returncode);
  150. }
  151.  
  152. /*
  153. ** Device Close vector.
  154. **
  155. ** a1 - IOReq
  156. ** a6 - Device Pointer
  157. **
  158. */
  159.  
  160. BPTR ASM DevClose(REG(a1) struct IOSana2Req *ios2,
  161.           REG(a6) struct SLIPDevice *SLIPDevice)
  162. {
  163.     struct SLIPDevUnit *sdu;
  164.     BPTR seglist = 0L;
  165.  
  166.     ObtainSemaphore(&SLIPDevice->sd_Lock);
  167.  
  168.     sdu = (struct SLIPDevUnit *)ios2->ios2_Req.io_Unit;
  169.  
  170.     /* Trash the io_Device and io_Unit fields so that any attempt to use this
  171.        request will die immediatly. */
  172.  
  173.     ios2->ios2_Req.io_Device = (struct Device *) -1;
  174.     ios2->ios2_Req.io_Unit = (struct Unit *) -1;
  175.  
  176.     /* I always shut the unit process down if the open count drops to zero.
  177.        That way, if I need to expunge, I never have to Wait(). */
  178.  
  179.     sdu->sdu_Unit.unit_OpenCnt--;
  180.     if(!sdu->sdu_Unit.unit_OpenCnt)
  181.     {
  182.     ExpungeUnit(sdu);
  183.     }
  184.  
  185.     SLIPDevice->sd_Device.lib_OpenCnt--;
  186.  
  187.     ReleaseSemaphore(&SLIPDevice->sd_Lock);
  188.  
  189.     /* Check to see if we've been asked to expunge. */
  190.     if(SLIPDevice->sd_Device.lib_Flags & LIBF_DELEXP)
  191.     seglist = DevExpunge(SLIPDevice);
  192.  
  193.     return(seglist);
  194. }
  195.  
  196.  
  197. /*
  198. ** Device Expunge vector
  199. **
  200. ** a6 - Device base
  201. **
  202. ** Note: You may NEVER EVER Wait() in expunge. Period.
  203. **     Don't even *think* about it.
  204. */
  205.  
  206. BPTR ASM DevExpunge(REG(a6) struct SLIPDevice *SLIPDevice)
  207. {
  208.     BPTR seglist;
  209.     ULONG devbase;
  210.     LONG devbasesize;
  211.  
  212.     if(SLIPDevice->sd_Device.lib_OpenCnt)
  213.     {
  214.     /* Sorry, we're busy.  We'll expunge later on
  215.        if we can. */
  216.     SLIPDevice->sd_Device.lib_Flags |= LIBF_DELEXP;
  217.     seglist = (BPTR)0L;
  218.     }
  219.     else
  220.     {
  221.     /* Free up our library base and function table after
  222.        removing ourselves from the library list. */
  223.     Remove((struct Node *)SLIPDevice);
  224.     seglist = SLIPDevice->sd_SegList;
  225.  
  226.     devbase = (ULONG) SLIPDevice;
  227.  
  228.     devbasesize = (ULONG)SLIPDevice->sd_Device.lib_NegSize;
  229.     devbase = devbase - devbasesize;
  230.  
  231.     devbasesize += (ULONG)SLIPDevice->sd_Device.lib_PosSize;
  232.  
  233. #if DEBUG
  234.     uninitsyslog();
  235. #endif
  236.     FreeMem((APTR)devbase,devbasesize);
  237.     ExtDeviceBase = NULL;
  238.     }
  239.     return(seglist);
  240. }
  241.  
  242. /*
  243. ** InitSLIPUnit
  244. **
  245. ** Initialize (if needed) a new SLIP device Unit and process.
  246. **
  247. */
  248.  
  249. struct SLIPDevUnit *InitSLIPUnit(ULONG s2unit)
  250. {
  251.     struct SLIPDevice *SLIPDevice = SLIPBase;
  252.     struct SLIPDevUnit *sdu;
  253.     struct TagItem NPTags[]={NP_Entry, 0, NP_Name, 0, NP_Priority, SLIP_PRI, TAG_DONE, 0};
  254.     struct MsgPort *replyport;
  255.  
  256.     /* Check to see if the Unit is already up and running.  If
  257.        it is, just drop through.  If not, try to start it up. */
  258.  
  259.     if(!SLIPDevice->sd_Units[s2unit])
  260.     {
  261.     /* Open up dos.library */
  262.     if(SLIPDevice->sd_DOSBase = OpenLibrary("dos.library",37L))
  263.     {
  264.         /* Allocate a new Unit structure */
  265.         if(sdu = AllocMem(sizeof(struct SLIPDevUnit), MEMF_CLEAR|MEMF_PUBLIC))
  266.         {
  267.         /* Do some initialization on the Unit structure */
  268.  
  269.         NewList(&sdu->sdu_Unit.unit_MsgPort.mp_MsgList);
  270.         sdu->sdu_Unit.unit_MsgPort.mp_Node.ln_Type = NT_MSGPORT;
  271.         sdu->sdu_Unit.unit_MsgPort.mp_Flags = PA_IGNORE;
  272.         sdu->sdu_Unit.unit_MsgPort.mp_Node.ln_Name = (char *)SLIPName;
  273.  
  274.         sdu->sdu_UnitNum = s2unit;
  275.         sdu->sdu_Device = (struct Device *) SLIPDevice;
  276.  
  277.         /* Try to read in our configuration file */
  278.         if(ReadConfig(sdu))
  279.         {
  280.             /* Start up the unit process */
  281.             if(replyport = CreateMsgPort())
  282.             {
  283.             SLIPDevice->sd_Startup.Msg.mn_ReplyPort = replyport;
  284.             SLIPDevice->sd_Startup.Device = (struct Device *) SLIPDevice;
  285.             SLIPDevice->sd_Startup.Unit = (struct Unit *)sdu;
  286.  
  287.             NPTags[0].ti_Data = (ULONG) &DevProcCEntry;
  288.             NPTags[1].ti_Data = (ULONG) SLIPName;      /* Process name */
  289.             /* Rhialto: use opener's priority */
  290.             NPTags[2].ti_Data = (ULONG) FindTask(NULL)->tc_Node.ln_Pri;
  291.  
  292.             /*ExtDeviceBase = (struct Library *)SLIPDevice;*/
  293.  
  294.             if(sdu->sdu_Proc = CreateNewProc(NPTags))
  295.             {
  296.                 PutMsg(&sdu->sdu_Proc->pr_MsgPort,(struct Message *)&SLIPDevice->sd_Startup);
  297.                 WaitPort(replyport);
  298.                 GetMsg(replyport);
  299.             }
  300.             DeleteMsgPort(replyport);
  301.             }
  302.         }
  303.  
  304.         if(!sdu->sdu_Proc)
  305.         {
  306.             /* The Unit process couldn't start for some reason, so free the Unit structure. */
  307.             FreeMem(sdu,sizeof(struct SLIPDevUnit));
  308.         }
  309.         else
  310.         {
  311.             /* Set up the Unit structure pointer in the device base */
  312.             SLIPDevice->sd_Units[s2unit] = (struct Unit *)sdu;
  313.         }
  314.         }
  315.         CloseLibrary(SLIPDevice->sd_DOSBase);
  316.     }
  317.     }
  318.     return((struct SLIPDevUnit *)SLIPDevice->sd_Units[s2unit]);
  319. }
  320.  
  321. /*
  322. **
  323. ** ExpungeUnit
  324. **
  325. ** Tells a unit process to go away...
  326. **
  327. ** This function is called from the DevClose routine when the open count for a
  328. ** unit reaches zero.  This routine signals the unit process to exit and then
  329. ** waits for the unit process to acknowledge.  The unit structure is then
  330. ** freed.
  331. */
  332.  
  333. VOID ExpungeUnit(struct SLIPDevUnit *sdu)
  334. {
  335.     struct SLIPDevice *SLIPDevice = SLIPBase;
  336.     struct Task *unittask;
  337.  
  338.     unittask = (struct Task *)sdu->sdu_Proc;
  339.  
  340.     sdu->sdu_Proc = (struct Process *)FindTask(0L);
  341.  
  342.     Signal(unittask,SIGBREAKF_CTRL_F);
  343.     Wait(SIGBREAKF_CTRL_F);
  344.  
  345.     SLIPDevice->sd_Units[sdu->sdu_UnitNum] = NULL;
  346.  
  347.     FreeMem(sdu, sizeof(struct SLIPDevUnit));
  348. }
  349.  
  350. /*
  351. **
  352. ** ReadConfig
  353. **
  354. ** Attempt to read in and parse the driver's configuration file.
  355. **
  356. ** The files are named by ENV:SANA2/slipX.config where X is the decimal
  357. ** representation of the device's unit number.
  358. **
  359. */
  360.  
  361. BOOL ReadConfig(struct SLIPDevUnit *sdu)
  362. {
  363.     UBYTE *linebuff,buff[40];
  364.     STRPTR termchar;
  365.     struct RDArgs *rdargs;
  366.     BPTR ConfigFile;
  367.     LONG args[6];
  368.     BOOL status = FALSE;
  369.     ULONG linenum=0;
  370.     UWORD i;
  371.  
  372.     /* Create the name of our config file.. */
  373.     sprintf(buff,"ENV:SANA2/slip%ld.config",(ULONG)sdu->sdu_UnitNum);
  374.  
  375.     /* ...and open it. */
  376.     if(ConfigFile = Open(buff,MODE_OLDFILE))
  377.     {
  378.     /* Here, I use ReadArgs() to do the file parsing for me. */
  379.  
  380.     if(linebuff = AllocMem(256,MEMF_CLEAR|MEMF_PUBLIC))
  381.     {
  382.         if(rdargs = AllocDosObject(DOS_RDARGS, NULL))
  383.         {
  384.         while(FGets(ConfigFile, linebuff, 255))
  385.         {
  386.             linenum++;
  387.             if(linebuff[0] == '#') /* Skip comment lines */
  388.             continue;
  389.  
  390.             rdargs->RDA_Source.CS_Buffer = linebuff;
  391.             rdargs->RDA_Source.CS_Length = 256;
  392.             rdargs->RDA_Source.CS_CurChr = 0;
  393.  
  394.             /* ReadArgs() requires that the line be null-terminated
  395.                or funny things happen. */
  396.  
  397.             termchar = (STRPTR) linebuff + strlen(linebuff);
  398.             *termchar = '\n';
  399.             termchar++;
  400.             *termchar = 0;
  401.  
  402.             for(i = 0; i< 6; i++)
  403.             args[i]=0;
  404.  
  405.             /* Parse the line...*/
  406.  
  407.             if(ReadArgs("SERNAME/A,SERUNIT/A/N,SERBAUD/A/N,IPSTR/A,CD=CARRIERDETECT/S,7WIRE/S",args,rdargs))
  408.             {
  409.             strcpy(sdu->sdu_SerDevName,(STRPTR)args[0]);
  410.             sdu->sdu_SerUnitNum = *((ULONG *)args[1]);
  411.             sdu->sdu_BaudRate = *((ULONG *)args[2]);
  412.             sdu->sdu_StAddr = /* Rhialto */
  413.             sdu->sdu_HwAddr = IPToNum((STRPTR)args[3]);
  414.  
  415.             if(args[4])
  416.                 sdu->sdu_State |= SLIPUF_CD;
  417.  
  418.             if(args[5])
  419.                 sdu->sdu_State |= SLIPUF_7WIRE;
  420.  
  421.             status = TRUE;
  422.             FreeArgs(rdargs);
  423.             break;
  424.             }
  425.             else
  426.             {
  427.             struct Library *IntuitionBase;
  428.             struct EasyStruct es;
  429.             if(IntuitionBase = OpenLibrary("intuition.library",37L))
  430.             {
  431.                 es.es_StructSize=sizeof(struct EasyStruct);
  432.                 es.es_Flags=0;
  433.                 es.es_Title=(char *)SLIPName;
  434.                 es.es_TextFormat="Error in configuration file on line %ld.";
  435.                 es.es_GadgetFormat="Okay";
  436.                 EasyRequestArgs(NULL, &es, 0, &linenum);
  437.                 CloseLibrary(IntuitionBase);
  438.             }
  439.             break;
  440.             }
  441.  
  442.         }
  443.         FreeDosObject(DOS_RDARGS,rdargs);
  444.         }
  445.         FreeMem(linebuff, 256);
  446.     }
  447.     Close(ConfigFile);
  448.     }
  449.     return(status);
  450. }
  451.  
  452.  
  453. /*
  454. **
  455. ** BeginIO
  456. **
  457. ** This is the dispatch point for the driver's incoming IORequests.
  458. **
  459. */
  460.  
  461. #define SLIP_IMMEDIATES 0L
  462.  
  463. VOID ASM DevBeginIO(REG(a1) struct IOSana2Req *ios2,
  464.             REG(a6) struct SLIPDevice *SLIPDevice)
  465. {
  466.     ios2->ios2_Req.io_Message.mn_Node.ln_Type = NT_MESSAGE;
  467.  
  468.     if(ios2->ios2_Req.io_Command < S2_END)
  469.     {
  470.     if((1L << ios2->ios2_Req.io_Command) & SLIP_IMMEDIATES)
  471.     {
  472.         PerformIO(ios2);
  473.     }
  474.     else
  475.     {
  476.         ios2->ios2_Req.io_Flags &= ~IOF_QUICK;
  477.         PutMsg((struct MsgPort *)ios2->ios2_Req.io_Unit,(struct Message *)ios2);
  478.     }
  479.     }
  480.     else
  481.     {
  482.     ios2->ios2_Req.io_Error = IOERR_NOCMD;
  483.     TermIO(ios2);
  484.     }
  485. }
  486.  
  487. /*
  488. ** This routine is used to dispatch an IO request either from BeginIO
  489. ** or from the Unit process.
  490. */
  491. VOID PerformIO(struct IOSana2Req *ios2)
  492. {
  493.     struct SLIPDevUnit *sdu;
  494.  
  495.     sdu = (struct SLIPDevUnit *)ios2->ios2_Req.io_Unit;
  496.  
  497.     ios2->ios2_Req.io_Error = 0;
  498.  
  499.     switch(ios2->ios2_Req.io_Command)
  500.     {
  501.     case CMD_READ:            ReadPacket(sdu,ios2);
  502.                     break;
  503.  
  504.     case CMD_WRITE:         WritePacket(sdu,ios2);
  505.                     break;
  506.  
  507.     case S2_DEVICEQUERY:        DeviceQuery(sdu,ios2);
  508.                     break;
  509.  
  510.     case S2_GETSTATIONADDRESS:  GetStationAddress(sdu,ios2);
  511.                     break;
  512.  
  513.     case S2_CONFIGINTERFACE:    ConfigInterface(sdu,ios2);
  514.                     break;
  515.  
  516.     case S2_ADDMULTICASTADDRESS:
  517.     case S2_DELMULTICASTADDRESS:
  518.     case S2_MULTICAST:        ios2->ios2_Req.io_Error = S2ERR_NOT_SUPPORTED;
  519.                     ios2->ios2_WireError = S2WERR_GENERIC_ERROR;
  520.                     TermIO(ios2);
  521.                     break;
  522.  
  523.     case S2_BROADCAST:        WritePacket(sdu,ios2);
  524.                     break;
  525.  
  526.     case S2_TRACKTYPE:        TrackType(sdu,ios2);
  527.                     break;
  528.  
  529.     case S2_UNTRACKTYPE:        UnTrackType(sdu,ios2);
  530.                     break;
  531.  
  532.     case S2_GETTYPESTATS:        GetTypeStats(sdu,ios2);
  533.                     break;
  534.  
  535.     case S2_GETSPECIALSTATS:    GetSpecialStats(sdu,ios2);
  536.                     break;
  537.  
  538.     case S2_GETGLOBALSTATS:     GetGlobalStats(sdu,ios2);
  539.                     break;
  540.  
  541.     case S2_ONEVENT:        OnEvent(sdu,ios2);
  542.                     break;
  543.  
  544.     case S2_READORPHAN:        ReadOrphan(sdu,ios2);
  545.                     break;
  546.  
  547.     case S2_ONLINE:         Online(sdu,ios2);
  548.                     break;
  549.  
  550.     case S2_OFFLINE:        Offline(sdu,ios2);
  551.                     break;
  552.  
  553.     default:            ios2->ios2_Req.io_Error = IOERR_NOCMD;
  554.                     TermIO(ios2);
  555.                     break;
  556.     }
  557. }
  558.  
  559. /*
  560. ** This function returns any device specific statistics that
  561. ** we may have.  Unfortunately, we don't have and SLIP specific
  562. ** statistics.
  563. */
  564. VOID GetSpecialStats(struct SLIPDevUnit *sdu, struct IOSana2Req *ios2)
  565. {
  566.     struct Sana2SpecialStatHeader *stats;
  567.  
  568.     stats = (struct Sana2SpecialStatHeader *)ios2->ios2_StatData;
  569.  
  570. #if CSLIP
  571.     {
  572.     int count;
  573.     struct Sana2SpecialStatRecord *r;
  574.  
  575.     count = stats->RecordCountMax;
  576.     if (count > 11)
  577.         count = 11;
  578.     r = (struct Sana2SpecialStatRecord *)(stats + 1);
  579.     r = &r[count - 1];
  580.  
  581.     switch (count) {
  582.     case 11:
  583.         r->Type = S2SS_CSLIP_I_TOSSED;
  584.         r->String = "i_tossed";
  585.         r->Count = sdu->sdu_slcompress.sls_i_tossed;
  586.         r--;
  587.     case 10:
  588.         r->Type = S2SS_CSLIP_I_ERROR;
  589.         r->String = "i_error";
  590.         r->Count = sdu->sdu_slcompress.sls_i_error;
  591.         r--;
  592.     case 9:
  593.         r->Type = S2SS_CSLIP_I_COMPRESSED;
  594.         r->String = "i_compressed";
  595.         r->Count = sdu->sdu_slcompress.sls_i_compressed;
  596.         r--;
  597.     case 8:
  598.         r->Type = S2SS_CSLIP_I_UNCOMPRESSED;
  599.         r->String = "i_uncompressed";
  600.         r->Count = sdu->sdu_slcompress.sls_i_uncompressed;
  601.         r--;
  602.     case 7:
  603.         r->Type = S2SS_CSLIP_I_IP;
  604.         r->String = "i_ip";
  605.         r->Count = sdu->sdu_slcompress.sls_i_ip;
  606.         r--;
  607.     case 6:
  608.         r->Type = S2SS_CSLIP_O_MISSES;
  609.         r->String = "o_misses";
  610.         r->Count = sdu->sdu_slcompress.sls_o_misses;
  611.         r--;
  612.     case 5:
  613.         r->Type = S2SS_CSLIP_O_SEARCHES;
  614.         r->String = "o_searches";
  615.         r->Count = sdu->sdu_slcompress.sls_o_searches;
  616.         r--;
  617.     case 4:
  618.         r->Type = S2SS_CSLIP_O_COMPRESSED;
  619.         r->String = "o_compressed";
  620.         r->Count = sdu->sdu_slcompress.sls_o_compressed;
  621.         r--;
  622.     case 3:
  623.         r->Type = S2SS_CSLIP_O_UNCOMPRESSED;
  624.         r->String = "o_uncompressed";
  625.         r->Count = sdu->sdu_slcompress.sls_o_uncompressed;
  626.         r--;
  627.     case 2:
  628.         r->Type = S2SS_CSLIP_O_TCP;
  629.         r->String = "o_tcp";
  630.         r->Count = sdu->sdu_slcompress.sls_o_tcp;
  631.         r--;
  632.     case 1:
  633.         r->Type = S2SS_CSLIP_O_NONTCP;
  634.         r->String = "o_nontcp";
  635.         r->Count = sdu->sdu_slcompress.sls_o_nontcp;
  636.     case 0:
  637.         break;
  638.     }
  639.     
  640.     stats->RecordCountSupplied = count;
  641.     }
  642. #else
  643.     stats->RecordCountSupplied = 0;
  644. #endif
  645.     TermIO(ios2);
  646. }
  647.  
  648. /*
  649. ** This function returns the global statistics for the
  650. ** slip device.
  651. */
  652. VOID GetGlobalStats(struct SLIPDevUnit *sdu, struct IOSana2Req *ios2)
  653. {
  654.     struct Sana2DeviceStats *stats;
  655.  
  656.     stats = (struct Sana2DeviceStats *)ios2->ios2_StatData;
  657.  
  658.     stats->PacketsReceived    = sdu->sdu_Stats.PacketsReceived;
  659.     stats->PacketsSent        = sdu->sdu_Stats.PacketsSent;
  660.     stats->BadData        = sdu->sdu_Stats.BadData;
  661.     stats->Overruns        = sdu->sdu_Stats.Overruns;
  662.     stats->UnknownTypesReceived = sdu->sdu_Stats.UnknownTypesReceived;
  663.     stats->Reconfigurations    = sdu->sdu_Stats.Reconfigurations;
  664.     stats->LastStart.tv_secs    = sdu->sdu_Stats.LastStart.tv_secs;
  665.     stats->LastStart.tv_micro    = sdu->sdu_Stats.LastStart.tv_micro; /* Rhialto */
  666.  
  667.     /* Rhialto: huh?
  668.     ios2->ios2_Req.io_Error = S2ERR_NOT_SUPPORTED;
  669.     ios2->ios2_WireError = S2WERR_GENERIC_ERROR;
  670.      */
  671.     TermIO(ios2);
  672. }
  673.  
  674. /*
  675. ** This function returns statistics for a specific
  676. ** type of packet that is being tracked.  Unfortunately,
  677. ** SLIP can't differentiate between different packet
  678. ** types, which makes packet type tracking essentially
  679. ** useless as the numbers would essentially be the same
  680. ** as those found via S2_GETGLOBALSTATS.
  681. **
  682. ** Just to be thourough, I have arbitrarily picked
  683. ** the packet type for SLIP IP packets to be 2048, the
  684. ** same as tha used for Ethernet.  This will at least
  685. ** allow you to track IP packets.
  686. */
  687. VOID GetTypeStats(struct SLIPDevUnit *sdu, struct IOSana2Req *ios2)
  688. {
  689.     struct Sana2PacketTypeStats *stats;
  690.     struct SuperS2PTStats *sstats;
  691.  
  692.     ObtainSemaphore(&sdu->sdu_ListLock);
  693.  
  694.     stats = (struct Sana2PacketTypeStats *)ios2->ios2_StatData;
  695.     sstats = (struct SuperS2PTStats *)sdu->sdu_Track.mlh_Head;
  696.  
  697.     while(sstats->ss_Node.mln_Succ)
  698.     {
  699.     if(ios2->ios2_PacketType == sstats->ss_PType)
  700.     {
  701.         stats->PacketsSent = sstats->ss_Stats.PacketsSent;
  702.         stats->PacketsReceived = sstats->ss_Stats.PacketsReceived;
  703.         stats->BytesSent = sstats->ss_Stats.BytesSent;
  704.         stats->BytesReceived = sstats->ss_Stats.BytesReceived;
  705.         stats->PacketsDropped = sstats->ss_Stats.PacketsDropped;
  706.         break;
  707.     }
  708.     sstats = (struct SuperS2PTStats *)sstats->ss_Node.mln_Succ;
  709.     }
  710.     ReleaseSemaphore(&sdu->sdu_ListLock);
  711.     if(!sstats->ss_Node.mln_Succ)
  712.     {
  713.     ios2->ios2_Req.io_Error = S2ERR_BAD_STATE;
  714.     ios2->ios2_WireError = S2WERR_NOT_TRACKED;
  715.     }
  716.     TermIO(ios2);
  717. }
  718.  
  719. /*
  720. ** This function adds a packet type to the list
  721. ** of those that are being tracked.
  722. */
  723. VOID TrackType(struct SLIPDevUnit *sdu, struct IOSana2Req *ios2)
  724. {
  725.     struct SuperS2PTStats *stats;
  726.  
  727.     ObtainSemaphore(&sdu->sdu_ListLock);
  728.  
  729.     stats = (struct SuperS2PTStats *)sdu->sdu_Track.mlh_Head;
  730.  
  731.     while(stats->ss_Node.mln_Succ)
  732.     {
  733.     if(ios2->ios2_PacketType == stats->ss_PType)
  734.     {
  735.         ios2->ios2_Req.io_Error = S2ERR_BAD_STATE;
  736.         ios2->ios2_WireError = S2WERR_ALREADY_TRACKED;
  737.         break;    /* Rhialto */
  738.     }
  739.     stats = (struct SuperS2PTStats *)stats->ss_Node.mln_Succ;
  740.     }
  741.     if(!stats->ss_Node.mln_Succ)
  742.     {
  743.     if(stats = AllocMem(sizeof(struct SuperS2PTStats),MEMF_CLEAR|MEMF_PUBLIC))
  744.     {
  745.         stats->ss_PType = ios2->ios2_PacketType;    /* Rhialto */
  746.         if(ios2->ios2_PacketType == 2048)
  747.         sdu->sdu_IPTrack = stats;
  748.         AddTail((struct List *)&sdu->sdu_Track,(struct Node *)stats);
  749.     }
  750.     }
  751.     ReleaseSemaphore(&sdu->sdu_ListLock);
  752.  
  753.     TermIO(ios2);
  754. }
  755.  
  756. /*
  757. ** This function removes a packet type from the
  758. ** list of those that are being tracked.
  759. */
  760. VOID UnTrackType(struct SLIPDevUnit *sdu, struct IOSana2Req *ios2)
  761. {
  762.     struct SuperS2PTStats *stats;
  763.     struct SuperS2PTStats *stats_next;
  764.  
  765.     ObtainSemaphore(&sdu->sdu_ListLock);
  766.  
  767.     stats = (struct SuperS2PTStats *)sdu->sdu_Track.mlh_Head;
  768.  
  769.     while(stats->ss_Node.mln_Succ)
  770.     {
  771.     stats_next = (struct SuperS2PTStats *)stats->ss_Node.mln_Succ;
  772.     if(ios2->ios2_PacketType == stats->ss_PType)
  773.     {
  774.         if(ios2->ios2_PacketType == 2048)
  775.         sdu->sdu_IPTrack = NULL;
  776.         Remove((struct Node *)stats);
  777.         FreeMem(stats,sizeof(struct SuperS2PTStats));
  778.         stats = NULL;
  779.         break;
  780.     }
  781.     stats = stats_next;
  782.     }
  783.     if(stats)
  784.     {
  785.     ios2->ios2_Req.io_Error = S2ERR_BAD_STATE;
  786.     ios2->ios2_WireError = S2WERR_NOT_TRACKED;
  787.     }
  788.     ReleaseSemaphore(&sdu->sdu_ListLock);
  789.  
  790.     TermIO(ios2);
  791. }
  792.  
  793. /*
  794. ** This function is called whenever we receive a packet
  795. ** from the serial device driver.
  796. **
  797. */
  798. VOID PacketReceived(struct SLIPDevUnit *sdu, ULONG length)
  799. {
  800.     sdu->sdu_Stats.PacketsReceived++;
  801.  
  802.     if(sdu->sdu_IPTrack)
  803.     {
  804.     sdu->sdu_IPTrack->ss_Stats.PacketsReceived++;
  805.     sdu->sdu_IPTrack->ss_Stats.BytesReceived+=length;
  806.     }
  807. }
  808.  
  809. /*
  810. ** This function is called whenever a packet is
  811. ** sent to the serial device driver.
  812. */
  813. VOID PacketSent(struct SLIPDevUnit *sdu, ULONG length)
  814. {
  815.     sdu->sdu_Stats.PacketsSent++;
  816.  
  817.     if(sdu->sdu_IPTrack)
  818.     {
  819.     sdu->sdu_IPTrack->ss_Stats.PacketsSent++;
  820.     sdu->sdu_IPTrack->ss_Stats.BytesSent+=length;
  821.     }
  822. }
  823.  
  824. /*
  825. ** This function is called whenever a packet that
  826. ** is too large is received.
  827. */
  828. VOID PacketOverrun(struct SLIPDevUnit *sdu)
  829. {
  830. #if CSLIP
  831.     sl_uncompress_tcp(NULL, TYPE_ERROR, &sdu->sdu_slcompress);
  832. #endif
  833.     sdu->sdu_Stats.Overruns++;
  834.     DoEvent(sdu, S2EVENT_RX);
  835. }
  836.  
  837. /*
  838. ** This function is called whenever a packet with
  839. ** garbage data is encountered.
  840. */
  841. VOID ReceivedGarbage(struct SLIPDevUnit *sdu)
  842. {
  843. #if CSLIP
  844.     sl_uncompress_tcp(NULL, TYPE_ERROR, &sdu->sdu_slcompress);
  845. #endif
  846.     sdu->sdu_Stats.BadData++;
  847.     DoEvent(sdu, S2EVENT_RX);
  848. }
  849.  
  850. /*
  851. ** This function is called whenever a packet
  852. ** is dropped by the SLIP driver.
  853. */
  854. VOID PacketDropped(struct SLIPDevUnit *sdu)
  855. {
  856.     if(sdu->sdu_IPTrack)
  857.     {
  858.     sdu->sdu_IPTrack->ss_Stats.PacketsDropped++;
  859.     }
  860. }
  861.  
  862. /*
  863. ** This function is used to return an IO request
  864. ** back to the sender.
  865. */
  866. VOID TermIO(struct IOSana2Req *ios2)
  867. {
  868.     if(!(ios2->ios2_Req.io_Flags & IOF_QUICK))
  869.     ReplyMsg((struct Message *)ios2);
  870. }
  871.  
  872. /*
  873. ** The device AbortIO() entry point.
  874. **
  875. ** A1 - The IO request to be aborted.
  876. ** A3 - The unit pointer
  877. ** A6 - The device base.
  878. */
  879. ULONG ASM DevAbortIO(REG(a1) struct IOSana2Req *ios2,
  880.              REG(a3) struct SLIPDevUnit *sdu,
  881.              REG(a6) struct SLIPDevice *SLIPDevice)
  882. {
  883.     ULONG result = 0L;
  884.  
  885.     ObtainSemaphore(&sdu->sdu_ListLock);
  886.     if(ios2->ios2_Req.io_Message.mn_Node.ln_Type != NT_REPLYMSG)
  887.     {
  888.     switch(ios2->ios2_Req.io_Command)
  889.     {
  890.         case CMD_READ:    result=AbortReq(&sdu->sdu_Rx,ios2);
  891.                 break;
  892.  
  893.         case CMD_WRITE: result=AbortReq(&sdu->sdu_Tx,ios2);
  894.                 break;
  895.  
  896.         case S2_READORPHAN:    result=AbortReq(&sdu->sdu_RxOrph,ios2);
  897.                     break;
  898.  
  899.         case S2_ONEVENT:    result=AbortReq(&sdu->sdu_Events,ios2);
  900.                     break;
  901.  
  902.         default:        result=IOERR_NOCMD;
  903.                     break;
  904.     }
  905.     }
  906.     ReleaseSemaphore(&sdu->sdu_ListLock);
  907.     return(result);
  908. }
  909.  
  910. /*
  911. ** This funcion is used to locate an IO request in a linked
  912. ** list and abort it if found.
  913. */
  914. ULONG AbortReq(struct MinList *minlist, struct IOSana2Req *ios2)
  915. {
  916.     struct Node *node, *next;
  917.     ULONG result=IOERR_NOCMD;
  918.  
  919.     node = (struct Node *)minlist->mlh_Head;
  920.  
  921.     while(node->ln_Succ)
  922.     {
  923.     next = node->ln_Succ;
  924.  
  925.     if(node == (struct Node *)ios2)
  926.     {
  927.         Remove((struct Node *)ios2);
  928.         ios2->ios2_Req.io_Error = IOERR_ABORTED;
  929.         TermIO(ios2);
  930.         result = 0;
  931.     }
  932.     node = next;
  933.     }
  934.     return(result);
  935. }
  936.  
  937. /*
  938. ** This function handles S2_CONFIGINTERFACE commands.
  939. */
  940. VOID ConfigInterface(struct SLIPDevUnit *sdu, struct IOSana2Req *ios2)
  941. {
  942.  
  943.     /* Note: we may only be configured once. */
  944.     if(!(sdu->sdu_State & SLIPUF_CONFIG))
  945.     {
  946.     if(OpenSerial(sdu))
  947.     {
  948.         CopyMem(&sdu->sdu_StAddr,&ios2->ios2_SrcAddr,4);
  949.         sdu->sdu_State |= SLIPUF_CONFIG;
  950.     }
  951.     }
  952.     else
  953.     {
  954.     /* Sorry, we're already configured. */
  955.     ios2->ios2_Req.io_Error = S2ERR_BAD_STATE;
  956.     ios2->ios2_WireError = S2WERR_IS_CONFIGURED;
  957.     }
  958.     TermIO(ios2);
  959. }
  960.  
  961. /*
  962. ** This function handles S2_GETSTATIONADDRESS commands.
  963. **
  964. ** We don't really have a hardware address, so we will
  965. ** just clear the source address field.
  966. ** Rhialto: What we want is the config file address as hardware
  967. *8        address, and the S2_CONFIGINTERFACE address as current address.
  968. */
  969.  
  970. VOID GetStationAddress(struct SLIPDevUnit *sdu, struct IOSana2Req *ios2)
  971. {
  972.     memset(ios2->ios2_DstAddr, 0, SANA2_MAX_ADDR_BYTES);
  973.     memset(ios2->ios2_SrcAddr, 0, SANA2_MAX_ADDR_BYTES);
  974.     memcpy(ios2->ios2_SrcAddr, &sdu->sdu_StAddr, 4);
  975.     memcpy(ios2->ios2_DstAddr, &sdu->sdu_HwAddr, 4);
  976.  
  977.     TermIO(ios2);
  978. }
  979.  
  980. /*
  981. ** This function handles S2_DEVICEQUERY comands.
  982. ** Rhialto: Give the format of the data, and the *correct* size!
  983. */
  984. VOID DeviceQuery(struct SLIPDevUnit *sdu, struct IOSana2Req *ios2)
  985. {
  986.     struct Sana2DeviceQuery *sdq;
  987.  
  988.     sdq = (struct Sana2DeviceQuery *)ios2->ios2_StatData;
  989.  
  990.     sdq->DevQueryFormat = 0;
  991.     sdq->DeviceLevel = 0;
  992.     sdq->AddrFieldSize = 32;            /* 32-bit IP address */
  993.     sdq->MTU = SLIP_MTU;            /* 1006 byte max */
  994.     sdq->BPS = sdu->sdu_BaudRate;
  995. #if CSLIP
  996.     sdq->HardwareType = S2WireType_CSLIP;
  997. #else
  998.     sdq->HardwareType = S2WireType_SLIP;
  999. #endif
  1000.  
  1001.     sdq->SizeSupplied = sizeof(*sdq);
  1002.     TermIO(ios2);
  1003. }
  1004.  
  1005. /*
  1006. ** This function is used for handling CMD_WRITE
  1007. ** commands.
  1008. */
  1009. VOID WritePacket(struct SLIPDevUnit *sdu, struct IOSana2Req *ios2)
  1010. {
  1011.  
  1012.     /* Make sure that we are online. */
  1013.     if(sdu->sdu_State & SLIPUF_ONLINE)
  1014.     {
  1015.     /* Make sure it's a legal length. */
  1016.     if(ios2->ios2_DataLength <= SLIP_MTU)
  1017.     {
  1018.         /* See if our serial CMD_WRITE command is busy.  If it's not, send
  1019.            the IO request to SendPacket. */
  1020.         if(CheckIO((struct IORequest *)sdu->sdu_SerTx))
  1021.         {
  1022.         WaitIO((struct IORequest *)sdu->sdu_SerTx);
  1023.         SendPacket(sdu, ios2);
  1024.         }
  1025.         else
  1026.         {
  1027.         /* We'll have to queue the packet for later...*/
  1028.         ios2->ios2_Req.io_Flags &= ~IOF_QUICK;
  1029.         ObtainSemaphore(&sdu->sdu_ListLock);
  1030.         AddTail((struct List *)&sdu->sdu_Tx,(struct Node *)ios2);
  1031.         ReleaseSemaphore(&sdu->sdu_ListLock);
  1032.         }
  1033.     }
  1034.     else
  1035.     {
  1036.         /* Sorry, the packet is too long! */
  1037.         ios2->ios2_Req.io_Error = S2ERR_MTU_EXCEEDED;
  1038.         ios2->ios2_WireError = S2WERR_GENERIC_ERROR;
  1039.         TermIO(ios2);
  1040.         DoEvent(sdu,S2EVENT_TX);
  1041.     }
  1042.     }
  1043.     else
  1044.     {
  1045.     /* Sorry, we're offline */
  1046.     ios2->ios2_Req.io_Error = S2ERR_OUTOFSERVICE;
  1047.     ios2->ios2_WireError = S2WERR_UNIT_OFFLINE;
  1048.     TermIO(ios2);
  1049.     }
  1050. }
  1051.  
  1052. VOID SendPacket(struct SLIPDevUnit *sdu, struct IOSana2Req *ios2)
  1053. {
  1054.     struct IOExtSer *ioser;
  1055.     struct BufferManagement *bm;
  1056.     ULONG framelength;
  1057.  
  1058.     bm =(struct BufferManagement *) ios2->ios2_BufferManagement;
  1059.  
  1060.     /* Copy the data out of the packet into our temporary buffer. */
  1061.     if((*bm->bm_CopyFromBuffer)(sdu->sdu_TxBuff,ios2->ios2_Data,ios2->ios2_DataLength))
  1062.     {
  1063. #if CSLIP
  1064.     struct mbuf m;
  1065.     unsigned char type;
  1066.  
  1067.     m.m_off = sdu->sdu_TxBuff;
  1068.     m.m_len = ios2->ios2_DataLength;
  1069.  
  1070.     /* Appendix B.1  Living without a framing `type' byte */
  1071.  
  1072.     type = sl_compress_tcp(&m, &sdu->sdu_slcompress);
  1073.     m.m_off[0] |= type;
  1074.  
  1075.     /* Encode the packet in SLIP format */
  1076.     framelength=EncodeSLIP(m.m_off,sdu->sdu_TxSLIP,m.m_len);
  1077.     PacketSent(sdu,m.m_len);
  1078. #else
  1079.     /* Encode the packet in SLIP format */
  1080.     framelength=EncodeSLIP(sdu->sdu_TxBuff,sdu->sdu_TxSLIP,ios2->ios2_DataLength);
  1081.     PacketSent(sdu,ios2->ios2_DataLength);
  1082. #endif
  1083.  
  1084.     ioser = sdu->sdu_SerTx;
  1085.     ioser->IOSer.io_Data = sdu->sdu_TxSLIP;
  1086.     ioser->IOSer.io_Length = framelength;
  1087.     ioser->IOSer.io_Command = CMD_WRITE;
  1088.     ioser->IOSer.io_Error = 0;
  1089.     ioser->IOSer.io_Message.mn_Node.ln_Type = 0;
  1090.  
  1091.     /* Send the packet to the serial device driver */
  1092.     SendIO((struct IORequest *)ioser);
  1093.     }
  1094.     else
  1095.     {
  1096.     /* Something went wrong...*/
  1097.     ios2->ios2_Req.io_Error = S2ERR_NO_RESOURCES;
  1098.     ios2->ios2_WireError = S2WERR_BUFF_ERROR;
  1099.     DoEvent(sdu,S2EVENT_BUFF);
  1100.     }
  1101.     TermIO(ios2);
  1102. }
  1103.  
  1104. /*
  1105. ** This routine encodes a packet in SLIP format.
  1106. **
  1107. ** The format is quite simple.
  1108. **
  1109. ** SLIP Encoding:
  1110. **
  1111. ** SLIP_ESC    -> SLIP_ESC SLIP_ESC_ESC
  1112. ** SLIP_END    -> SLIP_ESC SLIP_ESC_END
  1113. **
  1114. ** The packet is preceded and terminated with a SLIP_END as prescribed by
  1115. ** rfc 1055.
  1116. **
  1117. */
  1118. ULONG EncodeSLIP(UBYTE *source, UBYTE *dest, ULONG length)
  1119. {
  1120.     UBYTE ch;
  1121.     UBYTE *current;
  1122.  
  1123.     current = dest;
  1124.  
  1125.     *current = SLIP_END;
  1126.     current++;
  1127.  
  1128.     while(length--)
  1129.     {
  1130.     ch = *source;
  1131.     source++;
  1132.  
  1133.     if(ch == SLIP_ESC)
  1134.     {
  1135.         *current = SLIP_ESC;
  1136.         current++;
  1137.         ch = SLIP_ESC_ESC;
  1138.     }
  1139.     else if(ch == SLIP_END)
  1140.     {
  1141.         *current = SLIP_ESC;
  1142.         current ++;
  1143.         ch = SLIP_ESC_END;
  1144.     }
  1145.     *current = ch;
  1146.     current++;
  1147.     }
  1148.     *current = SLIP_END;
  1149.     current++;
  1150.  
  1151.     return((ULONG)(current - dest));
  1152. }
  1153.  
  1154. /*
  1155. ** This routine handles CMD_READ commands.  We
  1156. ** always queue these unless we're offline.
  1157. */
  1158. VOID ReadPacket(struct SLIPDevUnit *sdu, struct IOSana2Req *ios2)
  1159. {
  1160.  
  1161.     if(sdu->sdu_State & SLIPUF_ONLINE)
  1162.     {
  1163.     /* Queue it... */
  1164.     ObtainSemaphore(&sdu->sdu_ListLock);
  1165.     AddTail((struct List *)&sdu->sdu_Rx,(struct Node *)ios2);
  1166. #if DEMANDREAD
  1167.     if (sdu->sdu_SerRx->IOSer.io_Message.mn_Node.ln_Type == NT_FREEMSG)
  1168.         QueueSerRequest(sdu);
  1169. #endif
  1170.     ReleaseSemaphore(&sdu->sdu_ListLock);
  1171.     }
  1172.     else
  1173.     {
  1174.     /* Sorry, we're offline */
  1175.     ios2->ios2_Req.io_Error = S2ERR_OUTOFSERVICE;
  1176.     ios2->ios2_WireError = S2WERR_UNIT_OFFLINE;
  1177.     TermIO(ios2);
  1178.     }
  1179. }
  1180.  
  1181. /*
  1182. ** This routine handles CMD_READORPHAN commands.  We
  1183. ** always queue these unless we're offline.
  1184. **
  1185. ** Note: These IO requests will never get satisfied.
  1186. **     Since SLIP doesn't contain packet type information,
  1187. **     there is no way to identify what type of packets
  1188. **     are being received or sent.  Thus, we simply ignore
  1189. **     the packet type and *assume* that the packets are
  1190. **     IP packets.
  1191. */
  1192. VOID ReadOrphan(struct SLIPDevUnit *sdu, struct IOSana2Req *ios2)
  1193. {
  1194.  
  1195.     if(sdu->sdu_State & SLIPUF_ONLINE)
  1196.     {
  1197.     /* Queue it...*/
  1198.     ObtainSemaphore(&sdu->sdu_ListLock);
  1199.     AddTail((struct List *)&sdu->sdu_RxOrph,(struct Node *)ios2);
  1200. #if DEMANDREAD
  1201.     if (sdu->sdu_SerRx->IOSer.io_Message.mn_Node.ln_Type == NT_FREEMSG)
  1202.         QueueSerRequest(sdu);
  1203. #endif
  1204.     ReleaseSemaphore(&sdu->sdu_ListLock);
  1205.     }
  1206.     else
  1207.     {
  1208.     /* Sorry, we're offline */
  1209.     ios2->ios2_Req.io_Error = S2ERR_OUTOFSERVICE;
  1210.     ios2->ios2_WireError = S2WERR_UNIT_OFFLINE;
  1211.     TermIO(ios2);
  1212.     }
  1213. }
  1214.  
  1215. /*
  1216. ** This routine initializes our IO requests and buffers
  1217. ** for serial i/o and SLIP encoding/decoding.
  1218. */
  1219. BOOL InitSerial(struct SLIPDevUnit *sdu)
  1220. {
  1221.     ULONG *clr;
  1222.     BOOL status = FALSE;
  1223.  
  1224.     for(clr = (ULONG *) &sdu->sdu_SerRx; clr <= (ULONG *) &sdu->sdu_TxSLIP; clr++)
  1225.     *clr = 0L;
  1226.  
  1227.     if(sdu->sdu_TxPort = CreateMsgPort())
  1228.     {
  1229.     if(sdu->sdu_SerTx = CreateIORequest(sdu->sdu_TxPort,sizeof(struct IOExtSer)))
  1230.     {
  1231.         if(sdu->sdu_RxPort = CreateMsgPort())
  1232.         {
  1233.         if(sdu->sdu_SerRx = CreateIORequest(sdu->sdu_RxPort,sizeof(struct IOExtSer)))
  1234.         {
  1235.             if(sdu->sdu_TxBuff = AllocMem((SLIP_MTU + BUF_SLOP) * 2 + MAX_HDR,MEMF_CLEAR|MEMF_PUBLIC))
  1236.             {
  1237.             sdu->sdu_RxBuff = sdu->sdu_TxBuff + SLIP_MTU + BUF_SLOP + MAX_HDR;
  1238.             sdu->sdu_RxBuffPtr = sdu->sdu_RxBuff;
  1239.  
  1240.             if(sdu->sdu_TxSLIP = AllocMem((SLIP_MTU*2 + BUF_SLOP) * 2,MEMF_CLEAR|MEMF_PUBLIC))
  1241.             {
  1242.                 sdu->sdu_RxSLIP = sdu->sdu_TxSLIP + SLIP_MTU*2 + BUF_SLOP;
  1243.                 {
  1244.                 status = TRUE;
  1245.                 }
  1246.             }
  1247.             }
  1248.         }
  1249.         }
  1250.     }
  1251.     }
  1252.     if(!status)
  1253.     DeinitSerial(sdu);
  1254.     return(status);
  1255. }
  1256.  
  1257. /*
  1258. ** This routine cleans up our serial i/o requests
  1259. ** and misc. buffers.
  1260. */
  1261. VOID DeinitSerial(struct SLIPDevUnit *sdu)
  1262. {
  1263.     if(sdu->sdu_SerTx)
  1264.     DeleteIORequest(sdu->sdu_SerTx);
  1265.  
  1266.     if(sdu->sdu_TxPort)
  1267.     DeleteMsgPort(sdu->sdu_TxPort);
  1268.  
  1269.     if(sdu->sdu_SerRx)
  1270.     DeleteIORequest(sdu->sdu_SerRx);
  1271.  
  1272.     if(sdu->sdu_RxPort)
  1273.     DeleteMsgPort(sdu->sdu_RxPort);
  1274.  
  1275.     if(sdu->sdu_TxBuff)
  1276.     FreeMem(sdu->sdu_TxBuff, (SLIP_MTU + BUF_SLOP) * 2 + MAX_HDR);
  1277.  
  1278.     if(sdu->sdu_TxSLIP)
  1279.     FreeMem(sdu->sdu_TxSLIP,(SLIP_MTU*2 + BUF_SLOP) * 2);
  1280. }
  1281.  
  1282. /*
  1283. ** This routine handles S2_ONEVNET commands.
  1284. */
  1285. VOID OnEvent(struct SLIPDevUnit *sdu, struct IOSana2Req *ios2)
  1286. {
  1287.  
  1288.     switch(ios2->ios2_WireError)
  1289.     {
  1290.     /* Special case.  We may already be online, in which
  1291.        case the IO request should return immediately. Otherwise
  1292.        we queue it for later. */
  1293.  
  1294.     case S2EVENT_ONLINE:
  1295.                 if(sdu->sdu_State & SLIPUF_ONLINE)
  1296.                     TermIO(ios2);
  1297.                 else
  1298.                 {
  1299.                     ObtainSemaphore(&sdu->sdu_ListLock);
  1300.                     AddTail((struct List *)&sdu->sdu_Events,(struct Node *)ios2);
  1301.                     ReleaseSemaphore(&sdu->sdu_ListLock);
  1302.                 }
  1303.                 break;
  1304.  
  1305.     /* Same as with S2EVENT_ONLINE, but the opposite
  1306.        happens. */
  1307.     case S2EVENT_OFFLINE:
  1308.                 if(sdu->sdu_State & SLIPUF_ONLINE)
  1309.                 {
  1310.                     ObtainSemaphore(&sdu->sdu_ListLock);
  1311.                     AddTail((struct List *)&sdu->sdu_Events,(struct Node *)ios2);
  1312.                     ReleaseSemaphore(&sdu->sdu_ListLock);
  1313.                 }
  1314.                 else
  1315.                     TermIO(ios2);
  1316.                 break;
  1317.  
  1318.     /* Just queue everything else. */
  1319.     default:
  1320.                 ObtainSemaphore(&sdu->sdu_ListLock);
  1321.                 AddTail((struct List *)&sdu->sdu_Events,(struct Node *)ios2);
  1322.                 ReleaseSemaphore(&sdu->sdu_ListLock);
  1323.                 break;
  1324.     }
  1325. }
  1326.  
  1327. /*
  1328. ** This routine opens the serial device driver and attempts to bring
  1329. ** the device online.
  1330. */
  1331. BOOL OpenSerial(struct SLIPDevUnit *sdu)
  1332. {
  1333.     BOOL status = TRUE;
  1334.     ULONG odflags;
  1335.  
  1336.     sdu->sdu_SerRx->IOSer.io_Device = NULL;
  1337.  
  1338.     odflags = SERF_XDISABLED|SERF_RAD_BOOGIE;
  1339.     if(sdu->sdu_State & SLIPUF_7WIRE)
  1340.     odflags |= SERF_7WIRE;
  1341.  
  1342.     /* Rhialto: odflags must be in io_SerFlags, not in OpenDevice! */
  1343.     sdu->sdu_SerTx->io_SerFlags = odflags;
  1344.  
  1345.     if(!OpenDevice(sdu->sdu_SerDevName,sdu->sdu_SerUnitNum,(struct IORequest *)sdu->sdu_SerTx,0))
  1346.     {
  1347.     /* Set up our serial parameters */
  1348.     sdu->sdu_SerRx->IOSer.io_Device = sdu->sdu_SerTx->IOSer.io_Device;
  1349.     sdu->sdu_SerRx->IOSer.io_Unit = sdu->sdu_SerTx->IOSer.io_Unit;
  1350.  
  1351.     sdu->sdu_SerTx->IOSer.io_Command = SDCMD_SETPARAMS;
  1352.     sdu->sdu_SerTx->io_Baud = sdu->sdu_BaudRate;
  1353.     sdu->sdu_SerTx->io_RBufLen = 16384L;
  1354.     sdu->sdu_SerTx->io_ReadLen = 8;
  1355.     sdu->sdu_SerTx->io_WriteLen = 8;
  1356.     sdu->sdu_SerTx->io_StopBits = 1;
  1357.     sdu->sdu_SerTx->io_SerFlags = odflags;
  1358. #if EOFMODE
  1359.     sdu->sdu_SerTx->io_TermArray.TermArray0 =
  1360.     sdu->sdu_SerTx->io_TermArray.TermArray1 =
  1361.                 0x01010101 * ((unsigned char)SLIP_END);
  1362. #endif
  1363.     if(!DoIO((struct IORequest *)sdu->sdu_SerTx))
  1364.     {
  1365.         /* Assume we're now online */
  1366.         sdu->sdu_State |= SLIPUF_ONLINE;
  1367.  
  1368.         /* Are we checking for serial detect? */
  1369.         if(sdu->sdu_State & SLIPUF_CD)
  1370.         {
  1371.         sdu->sdu_SerTx->IOSer.io_Command = SDCMD_QUERY;
  1372.         if(!DoIO((struct IORequest *)sdu->sdu_SerTx))
  1373.         {
  1374.             if(sdu->sdu_SerTx->io_Status & (1<<5))
  1375.             {
  1376.             /* Sorry, no carrier, shut down the serial driver
  1377.                and set our state to offline. */
  1378.             CloseDevice((struct IORequest *)sdu->sdu_SerTx);
  1379.             sdu->sdu_State &= ~SLIPUF_ONLINE;
  1380.             }
  1381.         }
  1382.         else
  1383.             status = FALSE;
  1384.         }
  1385.         if(status)
  1386.         {
  1387.         /* Queue up the initial CMD_READ command for the
  1388.            serial driver. */
  1389.         sdu->sdu_SerRx->IOSer.io_Command = CMD_READ;
  1390.         sdu->sdu_SerRx->IOSer.io_Length = 1;
  1391.         sdu->sdu_SerRx->IOSer.io_Data = sdu->sdu_RxSLIP;
  1392. #if EOFMODE
  1393.         sdu->sdu_SerRx->io_SerFlags = SERF_EOFMODE|odflags;
  1394.         sdu->sdu_SerRx->io_TermArray.TermArray0 =
  1395.         sdu->sdu_SerRx->io_TermArray.TermArray1 =
  1396.                     0x01010101 * ((unsigned char)SLIP_END);
  1397. #else
  1398.         sdu->sdu_SerRx->io_SerFlags = odflags;
  1399. #endif
  1400.         SendIO((struct IORequest *)sdu->sdu_SerRx);
  1401.         }
  1402.     }
  1403.     else
  1404.         status = FALSE;
  1405.  
  1406.     if(!status)
  1407.         CloseDevice((struct IORequest *)sdu->sdu_SerTx);
  1408.     }
  1409.     else
  1410.     {
  1411.     struct Library *IntuitionBase;
  1412.     struct EasyStruct es;
  1413.     ULONG args[2];
  1414.     args[0]=(ULONG)sdu->sdu_SerDevName;
  1415.     args[1]=(ULONG)sdu->sdu_SerUnitNum;
  1416.     if(IntuitionBase = OpenLibrary("intuition.library",37L))
  1417.     {
  1418.         es.es_StructSize=sizeof(struct EasyStruct);
  1419.         es.es_Flags=0;
  1420.         es.es_Title=(char *)SLIPName;
  1421.         es.es_TextFormat="Couldn't open %s unit %ld.";
  1422.         es.es_GadgetFormat="Okay";
  1423.         EasyRequestArgs(NULL, &es, 0, (APTR)args);
  1424.         CloseLibrary(IntuitionBase);
  1425.     }
  1426.     status = FALSE;
  1427.     }
  1428.     if(sdu->sdu_State & SLIPUF_ONLINE)
  1429.     MarkTimeOnline(sdu);
  1430.  
  1431.     return(status);
  1432. }
  1433.  
  1434. /*
  1435. ** This routine gets the current system time and stores
  1436. ** it in our global statistics structure.
  1437. */
  1438.  
  1439. VOID MarkTimeOnline(struct SLIPDevUnit *sdu)
  1440. {
  1441.     register struct Library *TimerBase;
  1442.     struct timerequest *treq;
  1443.  
  1444.     if(treq = (struct timerequest *)AllocMem(sizeof(struct timerequest),MEMF_PUBLIC|MEMF_CLEAR))
  1445.     {
  1446.     if(!OpenDevice("timer.device",UNIT_MICROHZ,(struct IORequest *)treq,0L))
  1447.     {
  1448.         TimerBase = (struct Library *)treq->tr_node.io_Device;
  1449.         GetSysTime(&sdu->sdu_Stats.LastStart);
  1450.         CloseDevice((struct IORequest *)treq);
  1451.     }
  1452.     FreeMem(treq,sizeof(struct timerequest));
  1453.     }
  1454. }
  1455.  
  1456. /*
  1457. ** This routine aborts any pending activity with the serial
  1458. ** device driver and then brings the slip driver offline.
  1459. */
  1460. VOID CloseSerial(struct SLIPDevUnit *sdu)
  1461. {
  1462.     AbortIO((struct IORequest *)sdu->sdu_SerRx);
  1463.     WaitIO((struct IORequest *)sdu->sdu_SerRx);
  1464.  
  1465.     while(GetMsg(sdu->sdu_RxPort));
  1466.  
  1467.     AbortIO((struct IORequest *)sdu->sdu_SerTx);
  1468.     WaitIO((struct IORequest *)sdu->sdu_SerTx);
  1469.  
  1470.     while(GetMsg(sdu->sdu_TxPort));
  1471.  
  1472.     CloseDevice((struct IORequest *)sdu->sdu_SerRx);
  1473.  
  1474.     sdu->sdu_State &= ~SLIPUF_ONLINE;
  1475. }
  1476.  
  1477. /*
  1478. ** This routime handles CMD_ONLINE commands.
  1479. */
  1480. VOID Online(struct SLIPDevUnit *sdu, struct IOSana2Req *ios2)
  1481. {
  1482.  
  1483.     if(!(sdu->sdu_State & SLIPUF_ONLINE))
  1484.     {
  1485.     /* We're offline. Try to go online. */
  1486.     if(OpenSerial(sdu))
  1487.     {
  1488.         if(sdu->sdu_State & SLIPUF_ONLINE)
  1489.         {
  1490.         /* In case someone wants to know...*/
  1491.         DoEvent(sdu, S2EVENT_ONLINE);
  1492.         }
  1493.         else
  1494.         {
  1495.         /* Sorry, the attempt to go online failed. */
  1496.         ios2->ios2_Req.io_Error = S2ERR_OUTOFSERVICE;
  1497.         ios2->ios2_WireError = S2WERR_UNIT_OFFLINE;
  1498.         }
  1499.     }
  1500.     else
  1501.     {
  1502.         /* A general problem occured. */
  1503.         ios2->ios2_Req.io_Error = S2ERR_NO_RESOURCES;
  1504.         ios2->ios2_WireError = S2WERR_GENERIC_ERROR;
  1505.     }
  1506.     }
  1507.     TermIO(ios2);
  1508. }
  1509.  
  1510. /*
  1511. ** This routine handles CMD_OFFLINE commands.
  1512. */
  1513. VOID Offline(struct SLIPDevUnit *sdu, struct IOSana2Req *ios2)
  1514. {
  1515.     TermIO(ios2);
  1516.  
  1517.     if(sdu->sdu_State & SLIPUF_ONLINE)
  1518.     {
  1519.     /* We're online, so shut everything down. */
  1520.     CloseSerial(sdu);
  1521.     DoOffline(sdu);
  1522.     DoEvent(sdu,S2EVENT_OFFLINE);
  1523.     }
  1524. }
  1525.  
  1526. /*
  1527. ** This routine is called whenever an "important"
  1528. ** SANA-II event occurs.
  1529. */
  1530. VOID DoEvent(struct SLIPDevUnit *sdu, ULONG event)
  1531. {
  1532.     struct IOSana2Req *ios2;
  1533.     struct IOSana2Req *ios2_next;
  1534.  
  1535.     ObtainSemaphore(&sdu->sdu_ListLock);
  1536.  
  1537.     ios2 = (struct IOSana2Req *)sdu->sdu_Events.mlh_Head;
  1538.  
  1539.     while(ios2->ios2_Req.io_Message.mn_Node.ln_Succ)
  1540.     {
  1541.     ios2_next = (struct IOSana2Req *)ios2->ios2_Req.io_Message.mn_Node.ln_Succ;
  1542.  
  1543.     /* Is this the event they are looking for? */
  1544.     if(ios2->ios2_WireError == event)
  1545.     {
  1546.         Remove((struct Node *)ios2);
  1547.         TermIO(ios2);
  1548.     }
  1549.     ios2 = ios2_next;
  1550.     }
  1551.     ReleaseSemaphore(&sdu->sdu_ListLock);
  1552. }
  1553.  
  1554. /*
  1555. ** This routine is called whenever the device needs to
  1556. ** be taken offline.  We return any pending CMD_READ's
  1557. ** or CMD_WRITE's to their senders.
  1558. */
  1559. VOID DoOffline(struct SLIPDevUnit *sdu)
  1560. {
  1561.     struct IOSana2Req *ios2;
  1562.  
  1563.     ObtainSemaphore(&sdu->sdu_ListLock);
  1564.  
  1565.     while(ios2 = (struct IOSana2Req *)RemHead((struct List *)&sdu->sdu_Rx))
  1566.     {
  1567.     ios2->ios2_Req.io_Error = S2ERR_OUTOFSERVICE;
  1568.     ios2->ios2_WireError = S2WERR_UNIT_OFFLINE;
  1569.     TermIO(ios2);
  1570.     }
  1571.  
  1572.     while(ios2 = (struct IOSana2Req *)RemHead((struct List *)&sdu->sdu_Tx))
  1573.     {
  1574.     ios2->ios2_Req.io_Error = S2ERR_OUTOFSERVICE;
  1575.     ios2->ios2_WireError = S2WERR_UNIT_OFFLINE;
  1576.     TermIO(ios2);
  1577.     }
  1578.     ReleaseSemaphore(&sdu->sdu_ListLock);
  1579. }
  1580.  
  1581. /*
  1582. ** This routine is called whenever a CMD_WRITE request
  1583. ** has returned from the serial driver.
  1584. */
  1585. VOID ServiceTxPort(struct SLIPDevUnit *sdu)
  1586. {
  1587.     struct IOSana2Req *ios2;
  1588.  
  1589.     /* See if we have any pending CMD_WRITE requests. */
  1590.     if(sdu->sdu_State & SLIPUF_ONLINE)
  1591.     {
  1592.     ObtainSemaphore(&sdu->sdu_ListLock);
  1593.     ios2 = (struct IOSana2Req *)RemHead((struct List *)&sdu->sdu_Tx);
  1594.     ReleaseSemaphore(&sdu->sdu_ListLock);
  1595.  
  1596.     if(ios2)
  1597.     {
  1598.         SendPacket(sdu, ios2);
  1599.         sdu->sdu_NoMore = 1;
  1600.     }
  1601.     }
  1602.     else
  1603.     sdu->sdu_NoMore = 1;
  1604. }
  1605.  
  1606. /*
  1607. ** This routine is called whenever a CMD_READ request
  1608. ** returns from the serial driver.  It decodes the
  1609. ** packet data and tries to build complete packets.
  1610. */
  1611. VOID DoSerial(struct SLIPDevUnit *sdu, struct IOExtSer *ioSer)
  1612. {
  1613.     UBYTE *rx_ptr,*packet_ptr;
  1614.     UBYTE rx_byte, packet_byte;
  1615.     ULONG length;
  1616.  
  1617.     packet_ptr = sdu->sdu_RxBuffPtr;
  1618.     rx_ptr = sdu->sdu_RxSLIP;
  1619.  
  1620.     length = ioSer->IOSer.io_Actual;    /* Rhialto: Was io_Length */
  1621.  
  1622.     while(length--)
  1623.     {
  1624.     rx_byte = packet_byte = *rx_ptr;
  1625.     rx_ptr++;
  1626.  
  1627.     /* Handle SLIP packet decoding...*/
  1628.     if(sdu->sdu_Escape)
  1629.     {
  1630.         if(rx_byte == SLIP_ESC_ESC)
  1631.         packet_byte = SLIP_ESC;
  1632.         else if(rx_byte = SLIP_ESC_END)
  1633.         packet_byte = SLIP_END;
  1634.         else
  1635.         ReceivedGarbage(sdu);           /* This packet may be hosed */
  1636.  
  1637.         sdu->sdu_Escape = FALSE;
  1638.     }
  1639.     else if(rx_byte == SLIP_ESC)
  1640.     {
  1641.         sdu->sdu_Escape = TRUE;
  1642.         continue;
  1643.     }
  1644.     else if(rx_byte == SLIP_END)
  1645.     {
  1646.         GotPacket(sdu,(ULONG)(packet_ptr - sdu->sdu_RxBuff));
  1647.         packet_ptr = sdu->sdu_RxBuff;
  1648.         continue;
  1649.     }
  1650.     *packet_ptr = packet_byte;
  1651.     packet_ptr++;
  1652.  
  1653.     if(((ULONG)(packet_ptr - sdu->sdu_RxBuff)) > SLIP_MTU)
  1654.     {
  1655.         packet_ptr = sdu->sdu_RxBuff;
  1656.         PacketOverrun(sdu);
  1657.     }
  1658.     }
  1659.     sdu->sdu_RxBuffPtr = packet_ptr;
  1660.  
  1661.     /* Queue up another CMD_READ request...*/
  1662. #if DEMANDREAD
  1663.     /* Rhialto: but only if we are sure that we won't drop that packet */
  1664.     /*ObtainSemaphore(&sdu->sdu_ListLock);*/
  1665.     /* Semaphore protection of sdu_Rx, sdu_RxOrph, and sdu_Tx is not
  1666.      * really necessary, since they are only accessed from the
  1667.      * Unit task, because there are no IMMEDIATE device commands.
  1668.      */
  1669.     if (!IsListEmpty((struct List *)&sdu->sdu_Rx) ||
  1670.     !IsListEmpty((struct List *)&sdu->sdu_RxOrph))
  1671.     QueueSerRequest(sdu);
  1672.     else
  1673.     sdu->sdu_SerRx->IOSer.io_Message.mn_Node.ln_Type = NT_FREEMSG;
  1674.     /*ReleaseSemaphore(&sdu->sdu_ListLock);*/
  1675. #else
  1676.     QueueSerRequest(sdu);
  1677. #endif
  1678. }
  1679.  
  1680. /*
  1681. ** This routine is called whenever we think we've got
  1682. ** a complete packet to satisfy a CMD_READ request.
  1683. */
  1684. VOID GotPacket(struct SLIPDevUnit *sdu, ULONG length)
  1685. {
  1686.     struct IOSana2Req *ios2;
  1687.     struct BufferManagement *bm;
  1688.  
  1689.     /* We ignore zero-length packets. These occur
  1690.        in between legal SLIP packets due to the
  1691.        way SLIP packets are framed. */
  1692.  
  1693.     if(length)
  1694.     {
  1695.     PacketReceived(sdu,length);
  1696.     ObtainSemaphore(&sdu->sdu_ListLock);
  1697.  
  1698.     ios2 = (struct IOSana2Req *)RemHead((struct List *)&sdu->sdu_Rx);
  1699.  
  1700.     if(!ios2)
  1701.         ios2 = (struct IOSana2Req *)RemHead((struct List *)&sdu->sdu_RxOrph);
  1702.  
  1703.     ReleaseSemaphore(&sdu->sdu_ListLock);
  1704.  
  1705.     if(ios2)
  1706.     {
  1707. #if CSLIP
  1708.         /* Appendix B.1  Living without a framing `type' byte */
  1709.         struct mbuf m;
  1710.         unsigned char type;
  1711.  
  1712.         m.m_off = sdu->sdu_RxBuff;
  1713.         m.m_len = length;
  1714.  
  1715.         type = m.m_off[0];
  1716.  
  1717.         if (type & 0x80)
  1718.         type = TYPE_COMPRESSED_TCP;
  1719.         else if (type >= 0x70) {
  1720.         type = TYPE_UNCOMPRESSED_TCP;
  1721.         m.m_off[0] &= ~0x30;
  1722.         } else
  1723.         type = TYPE_IP;
  1724.         if (NULL == sl_uncompress_tcp(&m, type, &sdu->sdu_slcompress))
  1725.         return;
  1726.  
  1727.         bm = (struct BufferManagement *)ios2->ios2_BufferManagement;
  1728.  
  1729.         /* Copy the data into the protocol stack's buffer using its
  1730.            supplied callback routine. */
  1731.         if((*bm->bm_CopyToBuffer)(ios2->ios2_Data,m.m_off,m.m_len))
  1732.         {
  1733.         ios2->ios2_DataLength = m.m_len;
  1734.         }
  1735. #else
  1736.         bm = (struct BufferManagement *)ios2->ios2_BufferManagement;
  1737.  
  1738.         /* Copy the data into the protocol stack's buffer using its
  1739.            supplied callback routine. */
  1740.         if((*bm->bm_CopyToBuffer)(ios2->ios2_Data,sdu->sdu_RxBuff,length))
  1741.         {
  1742.         ios2->ios2_DataLength = length;
  1743.         }
  1744. #endif
  1745.         else
  1746.         {
  1747.         ios2->ios2_DataLength = 0;
  1748.         ios2->ios2_Req.io_Error = S2ERR_NO_RESOURCES;
  1749.         ios2->ios2_WireError = S2WERR_BUFF_ERROR;
  1750.         DoEvent(sdu,S2EVENT_BUFF);
  1751.         }
  1752.         TermIO(ios2);
  1753.     }
  1754.     else
  1755.         PacketDropped(sdu);
  1756.     }
  1757.     sdu->sdu_Escape = 0;
  1758. }
  1759.  
  1760. /*
  1761. ** This routine is called whenever we need to
  1762. ** get more data from the serial port.    We first
  1763. ** to a SDCMD_QUERY to see how much data is available,
  1764. ** if any.
  1765. ** Rhialto: without EOF mode, this makes the thing a real CPU hog,
  1766. ** as long as input is coming in and read requests are pending.
  1767. ** And since it runs at pri 5, that is a real disaster.
  1768. */
  1769. VOID QueueSerRequest(struct SLIPDevUnit *sdu)
  1770. {
  1771. #if EOFMODE == 0
  1772.     sdu->sdu_SerRx->IOSer.io_Command = SDCMD_QUERY;
  1773.     DoIO((struct IORequest *)sdu->sdu_SerRx);
  1774. #endif
  1775.  
  1776.     if(sdu->sdu_State & SLIPUF_CD)
  1777.     {
  1778. #if EOFMODE
  1779.     sdu->sdu_SerRx->IOSer.io_Command = SDCMD_QUERY;
  1780.     DoIO((struct IORequest *)sdu->sdu_SerRx);
  1781. #endif
  1782.     if(sdu->sdu_SerRx->io_Status & (1<<5))
  1783.     {
  1784.         /* Oops! We've lost carrier. Go offline. */
  1785.         CloseSerial(sdu);
  1786.         DoOffline(sdu);
  1787.         DoEvent(sdu,S2EVENT_OFFLINE);
  1788.         return;
  1789.     }
  1790.     }
  1791.     sdu->sdu_SerRx->IOSer.io_Command = CMD_READ;
  1792.     sdu->sdu_SerRx->IOSer.io_Data = sdu->sdu_RxSLIP;
  1793. #if EOFMODE
  1794.     sdu->sdu_SerRx->IOSer.io_Length = SLIP_MTU * 2 + 1;
  1795. #else
  1796.     /* Rhialto: This could lead to requesting more than the buffer
  1797.      * size! The serial.device has a 16K buffer. (See SDCMD_SETPARAMS)
  1798.      */
  1799.     sdu->sdu_SerRx->IOSer.io_Length = sdu->sdu_SerRx->IOSer.io_Actual;
  1800.  
  1801.     if (sdu->sdu_SerRx->IOSer.io_Length > (SLIP_MTU*2 + BUF_SLOP))
  1802.     sdu->sdu_SerRx->IOSer.io_Length = (SLIP_MTU*2 + BUF_SLOP);
  1803.     else
  1804.     /* If the number of bytes available is zero, queue a request
  1805.        for one byte. */
  1806.     if(!sdu->sdu_SerRx->IOSer.io_Length)
  1807.     sdu->sdu_SerRx->IOSer.io_Length = 1;
  1808. #endif
  1809.  
  1810.     SendIO((struct IORequest *)sdu->sdu_SerRx);
  1811. }
  1812.  
  1813. /*
  1814. ** This is the C entry point for the Unit process.
  1815. */
  1816.  
  1817. VOID ASM DevProcCEntry(VOID)
  1818. {
  1819.     struct Process *proc;
  1820.     struct SLIPDevUnit *sdu;
  1821.     struct IOExtSer *ioser;
  1822.     struct StartupMessage *sm;
  1823.     struct BufferManagement *bm;
  1824.     struct IOSana2Req *ios2;
  1825.     ULONG waitmask,signals;
  1826.     UBYTE signalbit;
  1827.  
  1828.     /* Find our Process pointer and wait for our startup
  1829.        message to arrive. */
  1830.  
  1831.     proc = (struct Process *)FindTask(0L);
  1832.  
  1833.     WaitPort(&proc->pr_MsgPort);
  1834.  
  1835.     /* Pull the startup message off of our process messageport. */
  1836.     sm = (struct StartupMessage *)GetMsg(&proc->pr_MsgPort);
  1837.  
  1838.     /* Grab our Unit pointer. */
  1839.     sdu = (struct SLIPDevUnit *)sm->Unit;
  1840.  
  1841.     /* Attempt to allocate a signal bit for our Unit MsgPort. */
  1842.     signalbit = AllocSignal(-1L);
  1843.     if(signalbit != -1)
  1844.     {
  1845.     /* Set up our Unit's MsgPort. */
  1846.     sdu->sdu_Unit.unit_MsgPort.mp_SigBit = signalbit;
  1847.     sdu->sdu_Unit.unit_MsgPort.mp_SigTask = (struct Task *)proc;
  1848.     sdu->sdu_Unit.unit_MsgPort.mp_Flags = PA_SIGNAL;
  1849.  
  1850.     /* Initialize our list semaphore */
  1851.     InitSemaphore(&sdu->sdu_ListLock);
  1852.  
  1853.     /* Initialize our linked lists. */
  1854.     NewList((struct List *)&sdu->sdu_Rx);
  1855.     NewList((struct List *)&sdu->sdu_RxOrph);
  1856.     NewList((struct List *)&sdu->sdu_Tx);
  1857.     NewList((struct List *)&sdu->sdu_Events);
  1858.     NewList((struct List *)&sdu->sdu_BuffMgmt);
  1859.     NewList((struct List *)&sdu->sdu_Track);
  1860.  
  1861. #if CSLIP
  1862.     /* Initialise the compression stuff */
  1863.     sl_compress_init(&sdu->sdu_slcompress, 16, 16);
  1864. #endif
  1865.  
  1866.     /* Initialize the serial stuff.  If all goes okay,
  1867.        set sdu->sdu_Proc to pointer to our unit process.
  1868.        This will let the Unit init code know that were
  1869.        are okay. */
  1870.  
  1871.     if(InitSerial(sdu))
  1872.         sdu->sdu_Proc = proc;
  1873.     }
  1874.     /* Reply to our startup message */
  1875.     ReplyMsg((struct Message *)sm);
  1876.  
  1877.     /* Check sdu->sdu_Proc to see if everything went okay up
  1878.        above. */
  1879.     if(sdu->sdu_Proc)
  1880.     {
  1881.     waitmask = (1L<<signalbit) | (1L<<sdu->sdu_RxPort->mp_SigBit) |
  1882.            (1L<<sdu->sdu_TxPort->mp_SigBit) | SIGBREAKF_CTRL_F;
  1883.  
  1884.     /* Loop...*/
  1885.  
  1886.     while(TRUE)
  1887.     {
  1888.         signals = Wait(waitmask);
  1889.  
  1890.         /* Have we been signaled to shut down? */
  1891.         if(signals & SIGBREAKF_CTRL_F)
  1892.         break;
  1893.  
  1894.         /* I use this flag to make sure I don't sit idle
  1895.            with a message sitting on one of my message ports. */
  1896.  
  1897.         sdu->sdu_NoMore = TRUE;    /* Make sure we run at least once. */
  1898.  
  1899.         while(sdu->sdu_NoMore)
  1900.         {
  1901.         sdu->sdu_NoMore = FALSE;
  1902.  
  1903.         if(ios2 = (struct IOSana2Req *)GetMsg((struct MsgPort *)sdu))
  1904.         {
  1905.             sdu->sdu_NoMore = TRUE;
  1906.             PerformIO(ios2);
  1907.         }
  1908.         if(ioser = (struct IOExtSer *)GetMsg(sdu->sdu_RxPort))
  1909.         {
  1910.             if(sdu->sdu_State & SLIPUF_ONLINE)
  1911.             {
  1912.             sdu->sdu_NoMore = TRUE;
  1913.             DoSerial(sdu, ioser);
  1914.             }
  1915.         }
  1916.         if(ioser = (struct IOExtSer *)GetMsg(sdu->sdu_TxPort))
  1917.         {
  1918.             sdu->sdu_NoMore = TRUE;
  1919.             ServiceTxPort(sdu);
  1920.         }
  1921.         }
  1922.     }
  1923.     /* If we're online, we need to shut everything down. */
  1924.     if(sdu->sdu_State & SLIPUF_ONLINE)
  1925.     {
  1926.         CloseSerial(sdu);
  1927.         FreeSignal(signalbit);
  1928.         while(bm = (struct BufferManagement *)RemHead((struct List *)&sdu->sdu_BuffMgmt))
  1929.         FreeMem(bm,sizeof(struct BufferManagement));
  1930.  
  1931.     }
  1932.     DeinitSerial(sdu);
  1933. #if CSLIP
  1934.     sl_compress_deinit(&sdu->sdu_slcompress);
  1935. #endif
  1936.  
  1937.     /* Signal the other side we're exiting.  Make sure that
  1938.        we exit before they wake up by using the same trick
  1939.        when replying to Workbench startup messages. */
  1940.  
  1941.     Forbid();
  1942.     Signal((struct Task *)sdu->sdu_Proc,SIGBREAKF_CTRL_F);
  1943.     }
  1944.     /* Something went wrong in the init code.  Drop out. */
  1945.     else
  1946.     {
  1947.     if(signalbit)
  1948.         FreeSignal(signalbit);
  1949.     }
  1950. }
  1951.  
  1952. /* List init routine. */
  1953. VOID NewList(struct List *list)
  1954. {
  1955.     list->lh_Head = (struct Node *)&list->lh_Tail;
  1956.     list->lh_Tail = NULL;
  1957.     list->lh_TailPred = (struct Node *)list;
  1958. }
  1959.